﻿using System;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Events;

namespace Microsoft.Samples.Office.UnifiedCommunications.Gadget.Config
{
    public static class GadgetConfigurationManager
    {
        private const string SETTINGS_SECTION = "GadgetSettings";

        #region Events

        private delegate void RaiseTop5ChangedEventDelegate(Top5ChangedEventArgs e);
        private static Delegate raiseTop5ChangedEvent;

        private delegate void RaiseFav5ChangedEventDelegate(Fav5ChangedEventArgs e);
        private static Delegate raiseFav5ChangedEvent;


        private static void RaiseTop5ChangedEvent(Top5ChangedEventArgs e)
        {
            GadgetEventManager.Instance.OnTop5ChangedEvent(e);
        }

        private static void RaiseFav5ChangedEvent(Fav5ChangedEventArgs e)
        {
            GadgetEventManager.Instance.OnFav5ChangedEvent(e);
        }

        #endregion

        #region Enums

        public enum ContactType
        {
            IM, PhoneCall, Email, CommunicatorCall,None
        }

        public enum Top5Setting
        {
            IM, Call, Email, Tagged, TeamMember, None
        }

        #endregion

        #region User Settings

        public static SettingsEWS GetUserSettingsEWS()
        {
            SettingsEWS curSettings = new SettingsEWS();
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                curSettings.EmailAddress = curSection.EmailAddress;
                curSettings.ExchangeServer = curSection.ExchangeServer;
                curSettings.DomainUser = curSection.DomainUser;
                curSettings.Password = curSection.Password;
                curSettings.EWSUrl = curSection.EWSUrl;
                curSettings.AutoDiscover = curSection.Autodiscover;
                curSettings.VoicemailEnabled = curSection.VoicemailEnabled;
                curSettings.DisplayName = curSection.DisplayName;
            }
            return curSettings;
        }

        public static void SetUserSettingsEWS(SettingsEWS curSettings)
        {
            //TODO do we need try-catch or error handling or do the config classes handle this gracefully?
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                curSection.EmailAddress = curSettings.EmailAddress;
                curSection.ExchangeServer = curSettings.ExchangeServer;
                curSection.DomainUser = curSettings.DomainUser;
                curSection.Password = curSettings.Password;
                curSection.EWSUrl = curSettings.EWSUrl;
                curSection.Autodiscover = curSettings.AutoDiscover;
                curSection.VoicemailEnabled = curSettings.VoicemailEnabled;
                curSection.DisplayName = curSettings.DisplayName;
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }

        }

        public static SettingsTop5 GetUserSettingsTop5()
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;
            return GetUserSettingsTop5(curSection);
        }

        public static SettingsTop5 GetUserSettingsTop5(GadgetSettingsSection curSection)
        {
            SettingsTop5 curSettings = new SettingsTop5();

            if (curSection != null)
            {
                curSettings.Top5UseIM = curSection.Top5UseIM;
                curSettings.Top5UseCall = curSection.Top5UseCall;
                curSettings.Top5UseEmail = curSection.Top5UseEmail;
                curSettings.Top5UseTagged = curSection.Top5UseTagged;
                curSettings.Top5UseTeamMember = curSection.Top5UseTeamMember;
            }
            return curSettings;
        }

        public static bool GetUserSettingsTop5BySetting(Top5Setting curSetting)
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                switch (curSetting)
                {
                    case Top5Setting.IM:
                        return curSection.Top5UseIM;
                    case Top5Setting.Call:
                        return curSection.Top5UseCall;
                    case Top5Setting.Email:
                        return curSection.Top5UseEmail;
                    case Top5Setting.Tagged:
                        return curSection.Top5UseTagged;
                    case Top5Setting.TeamMember:
                        return curSection.Top5UseTeamMember;
                    default:
                        return false;
                }
            }

            return false;
        }

        public static void SetUserSettingsTop5(SettingsTop5 curSettings)
        {
            //TODO do we need try-catch or error handling or do the config classes handle this gracefully?
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                curSection.Top5UseIM = curSettings.Top5UseIM;
                curSection.Top5UseCall = curSettings.Top5UseCall;
                curSection.Top5UseEmail = curSettings.Top5UseEmail;
                curSection.Top5UseTagged = curSettings.Top5UseTagged;
                curSection.Top5UseTeamMember = curSettings.Top5UseTeamMember;
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }

        }

        public static void SetUserSettingsTop5BySetting(Top5Setting curSetting, bool isChecked)
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                switch (curSetting)
                {
                    case Top5Setting.IM:
                        curSection.Top5UseIM = isChecked;
                        break;
                    case Top5Setting.Call:
                        curSection.Top5UseCall = isChecked;
                        break;
                    case Top5Setting.Email:
                        curSection.Top5UseEmail = isChecked;
                        break;
                    case Top5Setting.Tagged:
                        curSection.Top5UseTagged = isChecked;
                        break;
                    case Top5Setting.TeamMember:
                        curSection.Top5UseTeamMember = isChecked;
                        break;
                }
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }

        }

        #endregion

        #region Contacts Settings

        /// <summary>
        /// Gets current list of contacts, dirty read okay
        /// </summary>
        /// <returns></returns>
        public static ContactElementCollection GetCurrentContactList()
        {

            Configuration curConfig = LoadConfiguration();
            // update the last updated for contacts
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            return curSection.Contacts;

        }

        public static void ProcessContactUpdates(ContactElementCollection curContacts)
        {

            Configuration curConfig = LoadConfiguration();
            // update the last updated for contacts
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;
            string curContactID = String.Empty;
            ContactElement contactToUpdate;

            DateTime today;
            DateTime.TryParse(DateTime.Now.ToShortDateString(), out today);

            foreach (ContactElement updatedContact in curContacts)
            {
                curContactID = updatedContact.ContactID;
                contactToUpdate = curSection.Contacts[curContactID];
                if (contactToUpdate != null)
                {
                    contactToUpdate.EmailDayCount = updatedContact.EmailDayCount;
                    contactToUpdate.TeamMember = updatedContact.TeamMember;
                    contactToUpdate.LastUpdated = today;
                }
            }

            SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());

        }

        public static void ProcessContactUpdates(ContactElementCollection curContacts, IDictionary<string, ContactMessage> emailCounts)
        {
            DateTime today;
            DateTime.TryParse(DateTime.Now.ToShortDateString(), out today);


            foreach (ContactElement contact in curContacts)
            {
                if (emailCounts.ContainsKey(contact.DisplayName))
                {
                    ContactMessage message = emailCounts[contact.DisplayName];
                    if (!String.IsNullOrEmpty(message.from))
                    {
                        DateTime asOfTime;
                        DateTime.TryParse(message.asOfTime.ToShortDateString(), out asOfTime);

                        if (asOfTime > contact.LastUpdated)
                        {
                            SetContactSettings(
                                contact.ContactID,
                                contact.DisplayName,
                                ContactType.Email,
                                message.count,
                                contact.Tagged,
                                contact.TeamMember);
                        }
                        else
                        {

                            SetContactSettings(
                                contact.ContactID,
                                contact.DisplayName,
                                ContactType.Email,
                                -contact.EmailDayCount,
                                contact.Tagged,
                                contact.TeamMember);

                            SetContactSettings(
                                contact.ContactID,
                                contact.DisplayName,
                                ContactType.Email,
                                message.count,
                                contact.Tagged,
                                contact.TeamMember);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Increment day and total counts by contact type.  Reset day counts if date is greater than the last updated day.
        /// </summary>
        public static void SetContactSettings(string contactID, string displayName, ContactType curContactType, int numberOfContacts, bool tagged, bool teamMember)
        {
            Configuration curConfig = LoadConfiguration();
            // update the last updated for contacts
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            //TODO some error trapping here
            DateTime today;
            DateTime.TryParse(DateTime.Now.ToShortDateString(), out today);

            if (curSection != null)
            {
                // update the last updated for contacts
                PreprocessContacts(curSection);

                ContactElement newContact = new ContactElement();
                ContactElement curContact = curSection.Contacts[contactID];
                if (curContact != null)
                {
                    // current settings are in curContact, move to locals
                    DateTime curLastUpdated = curContact.LastUpdated;
                    int curIMTotalCount = curContact.IMTotalCount;
                    int curIMDayCount = curContact.IMDayCount;
                    int curCallTotalCount = curContact.CallTotalCount;
                    int curCallDayCount = curContact.CallDayCount;
                    int curCallCommunicatorTotalCount = curContact.CallCommunicatorTotalCount;
                    int curCallCommunicatorDayCount = curContact.CallCommunicatorDayCount;
                    int curEmailTotalCount = curContact.EmailTotalCount;
                    int curEmailDayCount = curContact.EmailDayCount;

                    bool dateChange = today != curLastUpdated;

                    newContact.LastUpdated = today;
                    newContact.ContactID = contactID;
                    newContact.DisplayName = displayName;
                    if (dateChange)
                    {
                        ClearDayCounts(newContact);
                    }
                    else
                    {
                        newContact.IMDayCount = curIMDayCount;
                        newContact.CallDayCount = curCallDayCount;
                        newContact.CallCommunicatorDayCount = curCallCommunicatorDayCount;
                        newContact.EmailDayCount = curEmailDayCount;
                    }
                    newContact.IMTotalCount = curIMTotalCount;
                    newContact.CallTotalCount = curCallTotalCount;
                    newContact.CallCommunicatorTotalCount = curCallCommunicatorTotalCount;
                    newContact.EmailTotalCount = curEmailTotalCount;
                    UpdateContactCount(newContact, curContactType, numberOfContacts);
                    newContact.Tagged = tagged;
                    newContact.TeamMember = teamMember;
                    curSection.Contacts.Remove(contactID);
                    curSection.Contacts.Add(newContact);
                }
                else
                {
                    newContact.LastUpdated = today;
                    newContact.ContactID = contactID;
                    newContact.DisplayName = displayName;
                    UpdateContactCount(newContact, curContactType, numberOfContacts);
                    newContact.Tagged = tagged;
                    newContact.TeamMember = teamMember;
                    curSection.Contacts.Add(newContact);
                }
                CalculateWeights(curSection);
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
               
            }
        }

        public static void SetContactSettings(string contactID, string displayName, int numberOfIM, int numberOfPhoneCall, int numberOfEmail, int numberOfCommunicatorCall, bool tagged, bool teamMember)
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            //TODO some error trapping here
            DateTime today;
            DateTime.TryParse(DateTime.Now.ToShortDateString(), out today);

            if (curSection != null)
            {
                // update the last updated for contacts
                PreprocessContacts(curSection);

                ContactElement newContact = new ContactElement();
                ContactElement curContact = curSection.Contacts[contactID];
                if (curContact != null)
                {
                    // current settings are in curContact, move to locals
                    DateTime curLastUpdated = curContact.LastUpdated;
                    int curIMTotalCount = curContact.IMTotalCount;
                    int curIMDayCount = curContact.IMDayCount;
                    int curCallTotalCount = curContact.CallTotalCount;
                    int curCallDayCount = curContact.CallDayCount;
                    int curCallCommunicatorTotalCount = curContact.CallCommunicatorTotalCount;
                    int curCallCommunicatorDayCount = curContact.CallCommunicatorDayCount;
                    int curEmailTotalCount = curContact.EmailTotalCount;
                    int curEmailDayCount = curContact.EmailDayCount;

                    bool dateChange = today != curLastUpdated;

                    newContact.LastUpdated = today;
                    newContact.ContactID = contactID;
                    newContact.DisplayName = displayName;
                    if (dateChange)
                    {
                        ClearDayCounts(newContact);
                    }
                    else
                    {
                        newContact.IMDayCount = curIMDayCount;
                        newContact.CallDayCount = curCallDayCount;
                        newContact.CallCommunicatorDayCount = curCallCommunicatorDayCount;
                        newContact.EmailDayCount = curEmailDayCount;
                    }
                    newContact.IMTotalCount = curIMTotalCount;
                    newContact.CallTotalCount = curCallTotalCount;
                    newContact.CallCommunicatorTotalCount = curCallCommunicatorTotalCount;
                    newContact.EmailTotalCount = curEmailTotalCount;
                    if (numberOfIM > 0)
                    {
                        UpdateContactCount(newContact, ContactType.IM, numberOfIM);
                    }
                    if (numberOfPhoneCall > 0)
                    {
                        UpdateContactCount(newContact, ContactType.PhoneCall, numberOfPhoneCall);
                    }
                    if (numberOfEmail > 0)
                    {
                        UpdateContactCount(newContact, ContactType.Email, numberOfEmail);
                    }
                    if (numberOfCommunicatorCall > 0)
                    {
                        UpdateContactCount(newContact, ContactType.CommunicatorCall, numberOfCommunicatorCall);
                    }
               
                    newContact.Tagged = tagged;
                    newContact.TeamMember = teamMember;
                    curSection.Contacts.Remove(contactID);
                    curSection.Contacts.Add(newContact);
                }
                else
                {
                    newContact.LastUpdated = today;
                    newContact.ContactID = contactID;
                    newContact.DisplayName = displayName;
                    if (numberOfIM > 0)
                    {
                        UpdateContactCount(newContact, ContactType.IM, numberOfIM);
                    }
                    if (numberOfPhoneCall > 0)
                    {
                        UpdateContactCount(newContact, ContactType.PhoneCall, numberOfPhoneCall);
                    }
                    if (numberOfEmail > 0)
                    {
                        UpdateContactCount(newContact, ContactType.Email, numberOfEmail);
                    }
                    if (numberOfCommunicatorCall > 0)
                    {
                        UpdateContactCount(newContact, ContactType.CommunicatorCall, numberOfCommunicatorCall);
                    }
                    newContact.Tagged = tagged;
                    newContact.TeamMember = teamMember;
                    curSection.Contacts.Add(newContact);
                }
                CalculateWeights(curSection);
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());

            }



        }

        private static void ClearDayCounts(ContactElement curContact)
        {
            curContact.CallCommunicatorDayCount = 0;
            curContact.CallDayCount = 0;
            curContact.EmailDayCount = 0;
            curContact.IMDayCount = 0;

        }

        private static void PreprocessContacts(GadgetSettingsSection curSection)
        {

            DateTime lastUpdated;
            DateTime.TryParse(curSection.ContactsUpdated.ToShortDateString(), out lastUpdated);
            DateTime current;
            DateTime.TryParse(DateTime.Now.ToShortDateString(), out current);
            // just check the dates (exclude the times)
            if (lastUpdated < current)
            {
                ClearAllDayCounts(curSection);
            }
            // update the contacts last updated
            curSection.ContactsUpdated = DateTime.Now;
        }

        private static void ClearAllDayCounts(GadgetSettingsSection curSection)
        {

                foreach (ContactElement curContact in curSection.Contacts)
                {
                    ClearDayCounts(curContact);
                }

        }

        /// <summary>
        /// Loop through the collection of ContactElements.  Determine weighting of each for top 5 calculation and update the 
        /// ContactElement Top5Weight property.  Add to generic List<ContactElement>, sort and reverse. Take top 5 or all (whichever is 
        /// greater) and update the Top5 section of the configuration.
        /// </summary>
        /// <param name="curSection"></param>
        private static void CalculateWeights(GadgetSettingsSection curSection)
        {

            // get weighting from config
            string top5Weight = ConfigurationManager.AppSettings["Top5Weight"];
            string[] weights = top5Weight.Split("|".ToCharArray());
            decimal curWeight;
            List<string> top5 = new List<string>();

            // get Top 5 configuration for user
            SettingsTop5 curSettings = GetUserSettingsTop5(curSection);

            foreach (ContactElement curContact in curSection.Contacts)
            {
                curWeight = GetContactWeight(curSection, curContact, weights, curSettings);
                curContact.Top5Weight = curWeight;
                if (curWeight > 0)
                {
                    top5.Add(curWeight.ToString() + "|" + curContact.ContactID + "|" + curContact.DisplayName);
                }
            }

            top5.Sort();
            top5.Reverse();
            int myCount = (top5.Count > 5)? 5 : top5.Count;
            for (int i = 0; i < myCount; i++)
            {
                // 5.4|george.durzi@contoso.com|George Durzi
                string curContactID = top5[i].Split(new char[] { '|' })[1];
                string curDisplayName = top5[i].Split(new char[] { '|' })[2];

                // adding all 5 entries, only raise the change event on the last one
                AddTop5(i + 1, curContactID, curDisplayName, curSection, ((i == myCount - 1) ? true : false));
            }

        }

        /// <summary>
        /// Determine the Top5Weight of a given ContactElement, based on user selection of categories to use and saved contact data.
        /// </summary>
        /// <param name="curSection"></param>
        /// <param name="curContact"></param>
        /// <param name="weights"></param>
        /// <param name="curSettings"></param>
        /// <returns></returns>
        private static decimal GetContactWeight(GadgetSettingsSection curSection, ContactElement curContact, string[] weights, SettingsTop5 curSettings)
        {
            int teamMemberMultiplier = Convert.ToInt32(ConfigurationManager.AppSettings["TeamMemberMultiplier"]);
            int taggedMultiplier = Convert.ToInt32(ConfigurationManager.AppSettings["Tagged2Multiplier"]);

            decimal totalIM = curSettings.Top5UseIM ? (Convert.ToDecimal(weights[0]) * curContact.IMDayCount) : 0;
            decimal totalCall = curSettings.Top5UseCall ? (Convert.ToDecimal(weights[1]) * (curContact.CallDayCount + curContact.CallCommunicatorDayCount)) : 0;
            decimal totalEmail = curSettings.Top5UseEmail ? (Convert.ToDecimal(weights[2]) * curContact.EmailDayCount) : 0;
            decimal totalTeam = ((curSettings.Top5UseTeamMember) && (IsInTeam("myteam"))) ? (Convert.ToDecimal(weights[3]) * 25) : 0;
            decimal totalTagged = ((curSettings.Top5UseTagged) && (curContact.Tagged)) ? (Convert.ToDecimal(weights[4]) * 25) : 0;

            return totalIM + totalCall + totalEmail + totalTeam + totalTagged;

        }

        private static bool IsInTeam(string curTeam)
        {
            // should compare user's team membership to membership in the contact's entry
            return true;

        }

        private static void UpdateContactCount(ContactElement curContact, ContactType curContactType, int numberOfContacts)
        {

            switch (curContactType)
            {
                case ContactType.IM:
                    curContact.IMDayCount += numberOfContacts;
                    curContact.IMTotalCount += numberOfContacts;
                    return;
                case ContactType.PhoneCall:
                    curContact.CallDayCount += numberOfContacts;
                    curContact.CallTotalCount += numberOfContacts;
                    return;
                case ContactType.CommunicatorCall:
                    curContact.CallCommunicatorDayCount += numberOfContacts;
                    curContact.CallCommunicatorTotalCount += numberOfContacts;
                    return;
                case ContactType.Email:
                    curContact.EmailDayCount += numberOfContacts;
                    curContact.EmailTotalCount += numberOfContacts;
                    return;
            }
        }

        #endregion

        #region Fav 5

        /// <summary>
        /// Get the current Favorite 5 list from the configuration file as a ContactElementCollection.
        /// This collection may be empty, so the count should be checked before using.
        /// </summary>
        /// <returns></returns>
        public static FavoriteElementCollection GetCurrentFav5List()
        {

            Configuration curConfig = LoadConfiguration();
            // update the last updated for contacts
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            return curSection.Favorite5;

        }

        public static void AddFavorite5(int orderKey, string contactID, string displayName, 
            string defaultClickAction, bool isPhoneNumber)
        {

            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                FavoriteElement curFav = new FavoriteElement();
                
                curFav.OrderKey = orderKey;
                curFav.ContactID = contactID;
                curFav.DisplayName = displayName;
                curFav.DefaultClickAction = defaultClickAction;
                curFav.IsPhoneNumber = isPhoneNumber;

                curSection.Favorite5.Remove(orderKey);
                curSection.Favorite5.Add(curFav);
                
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }

        }

        public static void ModifyFavorite5ClickAction(int orderKey, string defaultClickAction)
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                FavoriteElement fav5Contact = curSection.Favorite5.GetByOrderKey(orderKey);
                fav5Contact.DefaultClickAction = defaultClickAction;
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }
        }

        public static void ModifyFavorite5DisplayName(int orderKey, string displayName)
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                FavoriteElement fav5Contact = curSection.Favorite5.GetByOrderKey(orderKey);
                fav5Contact.DisplayName = displayName;
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }
        }

        public static void RemoveFavorite5ByKey(int orderKey)
        {

            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                curSection.Favorite5.Remove(orderKey);
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }

        }

        public static void RemoveFavorite5ByContactID(string contactID)
        {

            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                curSection.Favorite5.Remove(contactID);
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }

        }

        #endregion

        #region Top 5

        public static FavoriteElementCollection GetCurrentTop5List()
        {

            Configuration curConfig = LoadConfiguration();
            // update the last updated for contacts
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            return curSection.Top5;

        }

        public static void AddTop5(int orderKey, string contactID, string displayName, bool raiseEvent)
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;
            AddTop5(orderKey, contactID, displayName, curSection, raiseEvent);
            SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
        }

        /// <summary>
        /// Update the cached Top 5 list.  Top 5 only takes an orderKey and contactID
        /// </summary>
        /// <param name="orderKey"></param>
        /// <param name="contactID"></param>
        public static void AddTop5(int orderKey, string contactID, string displayName, GadgetSettingsSection curSection, bool raiseEvent)
        {
            if ((orderKey < 1) || (orderKey > 5))
            {
                Exception inner = null;
                throw new ArgumentOutOfRangeException("OrderKey must be between 1 and 5",inner);
            }
            if (curSection != null)
            {
                FavoriteElement curFav = new FavoriteElement();
                curFav.OrderKey = orderKey;
                curFav.ContactID = contactID;
                curFav.DisplayName = displayName;
                curSection.Top5.Remove(orderKey);
                curSection.Top5.Add(curFav);
                //raiseTop5ChangedEvent = new RaiseTop5ChangedEventDelegate(RaiseTop5ChangedEvent);
                //raiseTop5ChangedEvent.DynamicInvoke();
                RaiseTop5ChangedEvent(new Top5ChangedEventArgs());
          

            }
        }

        public static void RemoveTop5ByKey(int orderKey)
        {
            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                curSection.Top5.Remove(orderKey);
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
                raiseTop5ChangedEvent = new RaiseTop5ChangedEventDelegate(RaiseTop5ChangedEvent);
            }
        }

        public static void RemoveTop5ByContactID(string contactID)
        {

            Configuration curConfig = LoadConfiguration();
            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (curSection != null)
            {
                curSection.Top5.Remove(contactID);
                SaveConfiguration(curConfig, ConfigurationSaveMode.Minimal, EncryptConfiguration());
                raiseTop5ChangedEvent = new RaiseTop5ChangedEventDelegate(RaiseTop5ChangedEvent);
            }

        }

        #endregion

        #region Desktop Contacts

        public static DesktopContactElementCollection GetDesktopContacts()
        {
            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;
            return settingsSection.DesktopContacts;
        }

        public static void AddDesktopContact(int contactId, string sipUri, string displayName, bool visible)
        {
            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (settingsSection != null)
            {
                DesktopContactElement desktopContactElement = new DesktopContactElement()
                {
                    ContactId = contactId,
                    SipUri = sipUri,
                    DisplayName = displayName,
                    Visible = visible
                };

                settingsSection.DesktopContacts.Remove(contactId);
                settingsSection.DesktopContacts.Add(desktopContactElement);

                SaveConfiguration(config, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }
        }

        public static void EditDesktopContactDisplayName(int contactId, string displayName)
        {
            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (settingsSection != null)
            {
                DesktopContactElement desktopContactElement = settingsSection.DesktopContacts.GetByContactId(contactId);
                desktopContactElement.DisplayName = displayName;
                SaveConfiguration(config, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }
        }

        public static void EditDesktopContactVisibility(int contactId, bool visible)
        {
            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (settingsSection != null)
            {
                DesktopContactElement desktopContactElement = settingsSection.DesktopContacts.GetByContactId(contactId);
                desktopContactElement.Visible = visible;
                SaveConfiguration(config, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }
        }

        public static void RemoveDesktopContactById(int contactId)
        {
            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (settingsSection != null)
            {
                DesktopContactElement desktopContactElement = 
                    settingsSection.DesktopContacts.GetByContactId(contactId);

                string sipUri = desktopContactElement.SipUri;

                PresenceEventElementCollection presenceEventElements = 
                    GadgetConfigurationManager.GetPresenceEvents(sipUri);

                foreach (PresenceEventElement item in presenceEventElements)
                {
                    if (item.SipUri.Equals(sipUri, StringComparison.OrdinalIgnoreCase))
                    {
                        settingsSection.PresenceEvents.Remove(item.PresenceEventId);
                    }
                }

                settingsSection.DesktopContacts.Remove(contactId);
                SaveConfiguration(config, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }
        }

        #endregion

        #region Presence Events

        public static void AddPresenceEvent(string sipUri, DateTime presenceEventDateTime, string statusText)
        {
            RemoveOldPresenceEvents(sipUri);

            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            if (settingsSection != null)
            {
                Guid presenceEventId = Guid.NewGuid();

                PresenceEventElement presenceEventElement = new PresenceEventElement()
                    {
                        PresenceEventId = presenceEventId,
                        SipUri = sipUri,
                        PresenceEventDateTime = presenceEventDateTime,
                        StatusText = statusText
                    };

                settingsSection.PresenceEvents.Remove(presenceEventId);
                settingsSection.PresenceEvents.Add(presenceEventElement);

                SaveConfiguration(config, ConfigurationSaveMode.Minimal, EncryptConfiguration());
            }
        }

        public static PresenceEventElementCollection GetPresenceEvents(string sipUri)
        {
            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            PresenceEventElementCollection presenceEventColletion = settingsSection.PresenceEvents;
            PresenceEventElementCollection toReturn = new PresenceEventElementCollection();

            foreach (PresenceEventElement presenceEventElement in presenceEventColletion)
            {
                if (presenceEventElement.SipUri.Equals(sipUri, StringComparison.OrdinalIgnoreCase))
                {
                    toReturn.Add(presenceEventElement);
                }
            }

            return toReturn;
        }

        public static void RemoveOldPresenceEvents(string sipUri)
        {
            Configuration config = LoadConfiguration();
            GadgetSettingsSection settingsSection = config.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;

            PresenceEventElementCollection presenceEventColletion = GetPresenceEvents(sipUri);

            foreach (PresenceEventElement item in presenceEventColletion)
            {
                if (DateTime.Now.Subtract(item.PresenceEventDateTime).TotalHours > 24)
                    settingsSection.PresenceEvents.Remove(item);
            }

            SaveConfiguration(config, ConfigurationSaveMode.Minimal, EncryptConfiguration());
        }

        #endregion

        #region Configuration Tools

        private static Configuration LoadConfiguration()
        {
            Configuration curConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);

            GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;


            if (curSection != null)
            {
                if (curSection.SectionInformation.IsProtected)
                // Protect (encrypt)the section.
                {
                    curSection.SectionInformation.UnprotectSection();
                }
            }

            return curConfig;
        }

        private static void SaveConfiguration(Configuration curConfig, ConfigurationSaveMode saveMode, bool protect)
        {

            if (protect)
            {
                GadgetSettingsSection curSection = curConfig.GetSection(SETTINGS_SECTION) as GadgetSettingsSection;
                ProtectConfiguration(curSection);
                curConfig.Save(ConfigurationSaveMode.Full);
            }
            else
            {
                curConfig.Save(saveMode);
            }
        }

        private static void ProtectConfiguration(GadgetSettingsSection curSection)
        {

            if (((curSection != null) && (!curSection.SectionInformation.IsProtected) && (!curSection.SectionInformation.IsLocked) && (!curSection.SectionInformation.IsDeclared)))
            // Protect (encrypt)the section.
            {
                curSection.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");

                curSection.SectionInformation.ForceSave = true;
            }
        }

        private static bool EncryptConfiguration()
        {

            if (ConfigurationManager.AppSettings["EncryptConfiguration"] == Boolean.TrueString)
            {
                return true;
            }
            else
            {
                return false;
            }

        }

        #endregion
    }
}